package com.zk.algorithm.java.concurrent;

import com.zk.algorithm.annotation.Finished;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 两个线程分别打印 1- 100，A 打印偶数， B打印奇数
 *
 * @author zk
 */
@Finished(false)
public class TwoThreadPrintOddAndEven {

    public static class PrintTask {

        private Lock lock = new ReentrantLock();

        private Condition printOddCondition = lock.newCondition();
        private Condition printEvenCondition = lock.newCondition();

        private volatile int num = 0;
        private int total = 100;

        public PrintTask(int total) {
            this.total = total;
        }

        public void printOdd() {
            print(1, printEvenCondition, printOddCondition);
        }

        public void printEven() {
            print(0, printOddCondition, printEvenCondition);
        }

        private void print(int flag, Condition waitCondition, Condition sinalCondition) {
            while (true) {
                try {
                    lock.lock();

                    while (num % 2 == flag) {
                        waitCondition.await();
                    }

                    int cur = num++;
                    if (cur > total) {
                        break;
                    }

                    System.out.println(Thread.currentThread().getName() + " print " + num);
                    sinalCondition.signalAll();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }

    }

    public static void main(String...args) {
        PrintTask printTask = new PrintTask(10);

        new Thread(() -> printTask.printOdd(), "A").start();
        new Thread(() -> printTask.printOdd(), "B").start();
    }

}
